﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using FastNET.CleanAct.Client.ManagerEngineBusiness.DataObjects;
using FastNET.CleanAct.Common.Repository;

namespace FastNET.CleanAct.Tools.HomeTemplateEditor.Dialogs
{
    internal partial class SelectTemplate : Form
    {
        private readonly List<Identity> _bannedIDs;

        public SelectTemplate()
        {
            InitializeComponent();
            _bannedIDs = new List<Identity>();
        }

        public Identity SourceID { get; set; }

        public Identity? DestinationID
        {
            get
            {
                return TemplateTreeView.SelectedNode != null
                           ? (Identity?)((Identity)TemplateTreeView.SelectedNode.Tag)
                           : null;
            }
        }

        private void BanAllParents(IEnumerable<TemplateGroup> groups, Identity childID)
        {
            IEnumerable<TemplateGroup> parents = (from item in groups where item.ChildTemplateID == childID select item);

            foreach (TemplateGroup templateGroup in parents)
            {
                if (!_bannedIDs.Contains(templateGroup.ParentTemplateID))
                    _bannedIDs.Add(templateGroup.ParentTemplateID);
            }
        }

        private void BanAllChildren(Identity startID)
        {
            if (!_bannedIDs.Contains(startID))
                _bannedIDs.Add(startID);

            IList<TemplateGroup> groups = TemplateGroup.Retrieve(startID);

            foreach (TemplateGroup templateGroup in groups)
            {
                BanAllChildren(templateGroup.ChildTemplateID);
            }
        }

        private static TreeNode AddTemplate(TreeNodeCollection root, Template template)
        {
            string imageKey = template.IsBuiltIn ? "built-in" : "basic";

            TreeNode returnValue = root.Add(Guid.NewGuid().ToString(), template.Name, imageKey, imageKey);

            returnValue.Tag = template.ID;

            return returnValue;
        }

        private void AddSubTemplates(Identity parentID, IList<Template> templates, IList<TemplateGroup> groups, TreeNodeCollection root)
        {
            IEnumerable<Identity> childIDs = (from item in groups where item.ParentTemplateID == parentID select item.ChildTemplateID);
            IEnumerable<Template> children = (from item in templates where childIDs.Contains(item.ID) select item);

            foreach (Template template in children)
            {
                if (_bannedIDs.Contains(template.ID) || template.ID == SourceID)
                {
                    BanAllChildren(template.ID);
                    //BanAllParents(groups, template.ID);
                    continue;
                }

                bool foundItem = false;
                foreach (TemplateGroup group in from item in groups where item.ParentTemplateID == template.ID select item)
                {
                    if (group.ChildTemplateID != SourceID)
                    {
                        continue;
                    }
                    if (!_bannedIDs.Contains(group.ParentTemplateID))
                    {
                        _bannedIDs.Add(group.ParentTemplateID);
                    }
                    foundItem = true;
                    break;
                }
                if (foundItem)
                {
                    continue;
                }

                TreeNode newNode = AddTemplate(root, template);
                AddSubTemplates(template.ID, templates, groups, newNode.Nodes);
                if (_bannedIDs.Contains((Identity)newNode.Tag))
                {
                    newNode.Remove();
                }
            }
        }

        private void LoadTemplates()
        {
            IList<Template> templates = Template.Retrieve();
            IList<TemplateGroup> groups = TemplateGroup.Retrieve();

            IEnumerable<Identity> rootChildIDs = (from item in groups where item.ParentTemplateID == Guid.Empty select item.ChildTemplateID);
            IEnumerable<Template> rootTemplates = (from item in templates where rootChildIDs.Contains(item.ID) select item);

            List<Identity> linkedChildIDs = new List<Identity>();
            foreach (Identity id in from item in groups where item.ParentTemplateID != Guid.Empty select item.ParentTemplateID)
            {
                if (linkedChildIDs.Contains(id))
                {
                    continue;
                }

                linkedChildIDs.Add(id);
            }
            foreach (Identity id in from item in groups select item.ChildTemplateID)
            {
                if (linkedChildIDs.Contains(id))
                {
                    continue;
                }

                linkedChildIDs.Add(id);
            }

            TemplateTreeView.Nodes.Clear();

            foreach (Template template in rootTemplates)
            {
                if (_bannedIDs.Contains(template.ID) || template.ID == SourceID)
                {
                    BanAllChildren(template.ID);
                    //BanAllParents(groups, template.ID);
                    continue;
                }

                bool foundItem = false;
                foreach (TemplateGroup group in from item in groups where item.ParentTemplateID == template.ID select item)
                {
                    if (group.ChildTemplateID != SourceID)
                    {
                        continue;
                    }
                    if (!_bannedIDs.Contains(group.ParentTemplateID))
                    {
                        _bannedIDs.Add(group.ParentTemplateID);
                    }
                    foundItem = true;
                    break;
                }
                if (foundItem)
                {

                    continue;
                }

                TreeNode node = AddTemplate(TemplateTreeView.Nodes, template);
                AddSubTemplates(template.ID, templates, groups, node.Nodes);

                if (_bannedIDs.Contains((Identity)node.Tag))
                {
                    node.Remove();
                }
            }

            TemplateTreeView.ExpandAll();
        }

        private void SelectTemplate_Load(object sender, EventArgs e)
        {
            LoadTemplates();
            SelectButton.Enabled = false;

            try
            {
                new TemplateGroup(new Identity(Guid.Empty), SourceID);
                LinkRoot.Enabled = false;
                LinkTemplate.Checked = true;
            }
            catch
            {
            }
        }

        private void TemplateTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            SelectButton.Enabled = (TemplateTreeView.SelectedNode != null || LinkRoot.Checked);
        }

        private void TemplateTreeView_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
        {
            e.Cancel = true;
        }

        private void LinkRoot_CheckedChanged(object sender, EventArgs e)
        {
            TemplateTreeView.SelectedNode = null;
            TemplateTreeView.Enabled = false;
            SelectButton.Enabled = (TemplateTreeView.SelectedNode != null || LinkRoot.Checked);
        }

        private void LinkTemplate_CheckedChanged(object sender, EventArgs e)
        {
            TemplateTreeView.Enabled = true;
            SelectButton.Enabled = (TemplateTreeView.SelectedNode != null || LinkRoot.Checked);
        }

    }
}
